//
//  PMGrooveJoint.m
//  PezMonkey
//
//  Created by Spence DiNicolantonio on 10/31/09.
//  Copyright 2009 Necrosoft. All rights reserved.
//

/**
 * A subclass of PMConstraint for representing groove joints. PMGrooveJoints 
 * anchor one point of a rigid body to a groove on another rigid body. This groove
 * is a line segment defining the (groove) anchor's linear freedom of motion.
 */

#import "PMGrooveJoint.h"
#import "PMBody.h"


@implementation PMGrooveJoint


#pragma mark -
#pragma mark Init

/**
 * Returns a PMGrooveJoint object initialized by anchoring one given rigid body 
 * to a given groove segment and another given rigid body to its center of gravity.
 */
- (id)initWithGroove:(PMSegment)groove onBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody {
	return [self initWithGroove:groove 
						onBodyA:aBody anchor:PMVectZero 
						onBodyB:otherBody];
}

/**
 * Returns a PMGrooveJoint object initialized by anchoring one given rigid body 
 * to a given groove segment and another given rigid body to a given position 
 * reletive to the body's center of gravity.
 */
- (id)initWithGroove:(PMSegment)groove onBodyA:(PMBody *)aBody anchor:(PMAnchor)anchor onBodyB:(PMBody *)otherBody {
	if (![super init])
		return nil;
	
	// allocate and initialize cpConstraint
	constraint = cpGrooveJointNew(aBody.cpBody, otherBody.cpBody, groove.start, groove.end, anchor);
	
	// set body references
	self.bodyA = aBody;
	self.bodyB = otherBody;
	
	// reference this PMConstraint object with cpConstraint's data pointer
	// this is for internal use
	constraint->data = self;
	
	return self;
}


#pragma mark Convenience

/**
 * Creates and returns a PMGrooveJoint object initialized by anchoring one given 
 * rigid body to a given groove segment and another given rigid body to its center 
 * of gravity.
 */
+ (PMGrooveJoint *)grooveJointWithGroove:(PMSegment)groove onBodyA:(PMBody *)aBody bodyB:(PMBody *)otherBody {
	return [[[PMGrooveJoint alloc] initWithGroove:groove 
										  onBodyA:aBody 
											bodyB:otherBody] autorelease];
}

/**
 * Creates and returns a PMGrooveJoint object initialized by anchoring one given 
 * rigid body to a given groove segment and another given rigid body to a given 
 * position relative to the body's center of gravity.
 */
+ (PMGrooveJoint *)grooveJointWithGroove:(PMSegment)groove onBodyA:(PMBody *)aBody anchor:(PMAnchor)anchor onBodyB:(PMBody *)otherBody {
	return [[[PMGrooveJoint alloc] initWithGroove:groove 
										  onBodyA:aBody 
										   anchor:anchor
										  onBodyB:otherBody] autorelease];
}


#pragma mark -
#pragma mark Getters

/**
 * Returns the receiver's groove anchor position for bodyA.
 */
- (PMSegment)groove {
	PMVect start = ((cpGrooveJoint *) constraint)->grv_a;
	PMVect end = ((cpGrooveJoint *) constraint)->grv_b;
	return PMSegmentMake(start, end);
}

/**
 * Returns the receiver's joint anchor position for bodyA.
 */
- (PMAnchor)anchor {
	return cpGrooveJointGetAnchr2(constraint);
}


#pragma mark -
#pragma mark Setters

/**
 * Sets the groove anchor position of the receiver's bodyA to a given groove structure.
 */
- (void)setGroove:(PMSegment)groove {
	((cpGrooveJoint *) constraint)->grv_a = groove.start;
	((cpGrooveJoint *) constraint)->grv_b = groove.end;
}

/**
 * Sets the joint anchor position of the receiver's bodyB to a given point relative
 * the the body's center of gravity.
 */
- (void)setAnchor:(PMAnchor)anchor {
}

@end
